package org.dromara.monitor.admin.config;

import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：admin 监控 安全配置
 */
@EnableWebSecurity
@Configuration
public class SecurityConfig {

    /**
     * 管理员上下文路径变量
     * 用于存储管理员界面的上下文路径，是系统中一个重要的配置信息
     */
    private final String adminContextPath;

    /**
     * 构造函数SecurityConfig
     * 初始化安全配置类的上下文路径
     *
     * @param adminServerProperties 管理服务器属性，用于获取上下文路径信息
     */
    public SecurityConfig(AdminServerProperties adminServerProperties) {
        this.adminContextPath = adminServerProperties.getContextPath();
    }

    /**
     * 配置安全过滤器链
     * 此方法定义了应用的安全策略，包括请求的授权规则、登录和登出的配置等
     *
     * @param httpSecurity Spring Security的HttpSecurity对象，用于配置Web应用的安全设置
     * @return SecurityFilterChain对象，表示配置好的安全过滤器链
     * @throws Exception 配置过程中可能抛出的异常
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        // 创建一个处理认证成功后的处理程序
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        // 设置重定向的目标URL参数为"redirectTo"
        successHandler.setTargetUrlParameter("redirectTo");
        // 设置默认的重定向URL为管理界面的根路径
        successHandler.setDefaultTargetUrl(adminContextPath + "/");

        // 开始配置httpSecurity对象，定义安全策略
        return httpSecurity
            // 配置HTTP头部信息，禁用frame选项
            .headers((header) ->
                header.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
            // 配置请求的授权规则
            .authorizeHttpRequests((authorize) ->
                authorize.requestMatchers(
                        // 静态资源路径
                        new AntPathRequestMatcher(adminContextPath + "/assets/**"),
                        // 登录页面
                        new AntPathRequestMatcher(adminContextPath + "/login"),
                        // Actuator端点
                        new AntPathRequestMatcher("/actuator"),
                        // Actuator端点的其他请求
                        new AntPathRequestMatcher("/actuator/**")
                        //  以上路径都无需认证即可访问
                    ).permitAll()
                    // 所有其他请求都需要认证
                    .anyRequest().authenticated())
            // 配置表单登录
            .formLogin((formLogin) ->
                // 设置登录页面
                formLogin.loginPage(adminContextPath + "/login")
                    // 设置认证成功后的处理程序
                    .successHandler(successHandler))
            // 配置登出的URL
            .logout((logout) ->
                logout.logoutUrl(adminContextPath + "/logout"))
            // 配置HTTP Basic认证
            .httpBasic(Customizer.withDefaults())
            // 禁用CSRF防护
            .csrf(AbstractHttpConfigurer::disable)
            .build();
    }

}
